package org.lib.ws;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

import org.springframework.stereotype.Component;

/**
 * 前后端交互的类实现消息的接收推送(自己发送给所有人(不包括自己))
 * @author ben
 * @date 2021-11-12 21:00:25 CST
 */
@Component
@ServerEndpoint(value = "/ws2")
public class OneToManyWebSocket {

	private Consumer<Object> cs = System.out::println;
	
	/**
	 * 记录当前在线连接数
	 */
	private static AtomicInteger onlineCount = new AtomicInteger(0);
	
	/**
	 * 所有客户端
	 */
	private static Map<String, Session> clients = new ConcurrentHashMap<>(); 
	
	@OnOpen
	public void onOpen(Session session) {
		onlineCount.incrementAndGet();
		String sid = session.getId();
		clients.put(sid, session);
		cs.accept("onOpen: sid=" + sid + ", onlineCount=" + onlineCount + ", clients.size=" + clients.size());
	}
	
	@OnClose
	public void onClose(Session session) {
		onlineCount.decrementAndGet();
		String sid = session.getId();
		clients.remove(sid);
		cs.accept("onClose: sid=" + sid + ", onlineCount=" + onlineCount + ", clients.size=" + clients.size());
	}
	
	@OnMessage
	public void onMessage(String message, Session session) {
		cs.accept("服务端收到客户端[" + session.getId() + "]的消息:" + message);
		this.sendMessageToOthers(message, session);
	}
	
	@OnError
	public void onError(Session session, Throwable err) {
		cs.accept("发生错误：sid=" + session.getId() + ", e=" + err.getClass() + ", " + err.getMessage());
		err.printStackTrace();
	}

	/**
	 * 发送消息给其它client
	 * @author ben
	 * @date 2021-11-12 21:08:17 CST
	 * @param message
	 * @param session
	 */
	private void sendMessageToOthers(String message, Session session) {
		String sid = session.getId();
		clients.forEach((key, value)->{
			String vid = value.getId();
			if (!sid.equals(vid)) {
				cs.accept("send message from sid=" + sid + " to vid = " + vid + ": message=" + message);
				value.getAsyncRemote().sendText(message);
			}
		});
	}
	
}
